
/// 表达式， 控制流程
fn main() {

    // 语句组成
    // statement
    // statement
    // statement

    // 参数绑定
    let x = 5;

    // 表达式
    // x;
    // x + 1;
    // 15;

    // 块级表达式
    let y = {
        let x = 1;
        x + 1
    };

    #[allow(unused_must_use)]
    let z = {
        //* 注意以分号结尾，返回（）
        2 * y;
    };

    println!("x = {}", x);
    println!("y = {}", y);
    println!("z = {:?}", z);


    // 控制流程  if else for loop while match...
    let n = 50;
    if n < 0 {
        print!("{} is negative", n);
    } else if n > 0 {
        print!("{} is positive", n);
    } else {
        print!("{} is zero", n);
    }

    let big_n =
        if n < 10 && n > -10 {
            println!(", and is a small number, increase ten-fold");
            10 * n
        } else {
            println!(", and is a big number, halve the number");
            n / 2
        };
    println!("{} -> {}", n, big_n);

    // loop
    {
        let mut n = 1u8;
        loop {
            n += 1;
            if n % 2 == 0 {
                continue;
            }
            if n > 10 {
                break;
            }
            print!("{}", n);
        }
        println!("{}", n);
    }

    // 嵌套loop
    {
        #[allow(unused_labels)]
        #[allow(unreachable_code)]
        'level1: loop{
            println!("level1");
            'level2: loop{
                println!("level2");
                break 'level1;
            }
            println!("the black hole.");
        }
        println!("exit");
    }

    // loop中返回
    {
        let mut counter = 0;
        let a = loop{
            counter += 1;

            if counter == 10 {
                break counter * 2;
            }
        };
        println!("loop a = {}", a);
    }

    // while
    {
        let mut n = 1;

        while n < 20 {
            if n % 15 == 0 {
                println!("fizzbuzz");
            } else if n % 3 == 0 {
                println!("fizz");
            } else if n % 5 == 0 {
                println!("buzz");
            } else {
                println!("{}", n);
            }
            n += 1;
        }
    }

    // for
    {
        // 1..20  [1,20)
        // 1..=20  [1,20]
        for n in 1..20 {
            if n % 15 == 0 {
                println!("fizzbuzz");
            } else if n % 3 == 0 {
                println!("fizz");
            } else if n % 5 == 0 {
                println!("buzz");
            } else {
                println!("{}", n);
            }
        }
    }

    // for迭代

    {
        let names = vec!["Bob", "Frank", "Ferris"];

        for name in names.iter() {
            match name {
                &"Ferris" => println!("There is a rustacean among us!"),
                _ => println!("Hello {}", name),
            }
        }

        println!("names: {:?}", names);
    }

    {
        let names = vec!["Bob", "Frank", "Ferris"];

        for name in names.into_iter() {
            match name {
                "Ferris" => println!("There is a rustacean among us!"),
                _ => println!("Hello {}", name),
            }
        }

        // 参考“借用&移动”知识，这里的names被循环中移动使用了，所以这里不存在了
        // println!("names: {:?}", names);
    }

    {
        let mut names = vec!["Bob", "Frank", "Ferris"];

        for name in names.iter_mut() {
            *name = match name {
                &mut "Ferris" => "There is a rustacean among us!",
                _ => "Hello",
            }
        }

        // 允许被修改的集合(mut),使用的“借用”
        println!("names: {:?}", names);
    }


    // match
    {
        let number = 13;

        println!("Tell me about {}", number);
        match number {
            1 => println!("One!"),
            2 | 3 | 5 | 7 | 11 => println!("This is a prime"),
            13..=19 => println!("A teen"),
            _ => println!("Ain't special"),
        }

        let boolean = true;
        let binary = match boolean {
            false => 0,
            true => 1,
        };

        println!("{} -> {}", boolean, binary);
    }

    // match - 解构 - 元组，数组，切片，结构体，枚举，指针
    // 1 解构元组
    {
        let triple = (0, -2, 3);
        println!("triple {:?}", triple);
        match triple {
            (0, y, z) => println!("First is `0`, `y` is {:?}, and `z` is {:?}", y, z),
            (1, ..)   => println!("First is `1` and the rest doesn't matter"),
            _         => println!("It doesn't matter what they are"),
        }
    }

    // 2 解构数组
    {
        let array = [4, -2, 6];

        match array {
            [0, second, third] =>
                println!("array[0] = 0, array[1] = {}, array[2] = {}", second, third),
            [1, _, third] => println!(
                "array[0] = 1, array[2] = {} and array[1] was ignored",
                third
            ),
            [-1, second, ..] => println!(
                "array[0] = -1, array[1] = {} and all the other ones were ignored",
                second
            ),
            // @ 将
            [3, second, tail @ ..] => println!(
                "array[0] = 3, array[1] = {} and the other elements were {:?}",
                second, tail
            ),
            [first, middle @ .., last] => println!(
                "array[0] = {}, middle = {:?}, array[2] = {}",
                first, middle, last
            ),
        }
    }

    // 3.解构枚举
    {
        #[allow(dead_code)]
        enum Color {
            Red,
            Blue,
            Green,
            RGB(u32, u32, u32),
            HSV(u32, u32, u32),
            HSL(u32, u32, u32),
            CMY(u32, u32, u32),
            CMYK(u32, u32, u32, u32),
        }

        let color = Color::RGB(122, 17, 40);

        match color {
            Color::Red   => println!("The color is Red!"),
            Color::Blue  => println!("The color is Blue!"),
            Color::Green => println!("The color is Green!"),
            Color::RGB(r, g, b) =>
                println!("Red: {}, green: {}, and blue: {}!", r, g, b),
            Color::HSV(h, s, v) =>
                println!("Hue: {}, saturation: {}, value: {}!", h, s, v),
            Color::HSL(h, s, l) =>
                println!("Hue: {}, saturation: {}, lightness: {}!", h, s, l),
            Color::CMY(c, m, y) =>
                println!("Cyan: {}, magenta: {}, yellow: {}!", c, m, y),
            Color::CMYK(c, m, y, k) =>
                println!("Cyan: {}, magenta: {}, yellow: {}, key (black): {}!",
                    c, m, y, k),
        }
    }

    // 4.解构指针
    // 区分解构(&, ref, ref mut)，  解引用 (*)
    {
        let reference = &4;

        match reference {
            &val => println!("Got a value via destructuring: {:?}", val),
        }

        match *reference {
            val => println!("Got a value via dereferencing: {:?}", val),
        }

        let _not_a_reference = 3;

        let ref _is_a_reference = 3;

        let value = 5;
        let mut mut_value = 6;

        match value {
            ref r => println!("Got a reference to a value: {:?}", r),
        }

        match mut_value {
            ref mut m => {
                *m += 10;
                println!("We added 10. `mut_value`: {:?}", m);
            },
        }
    }

    // 5. 解构结构体
    {
        struct Foo {
            x: (u32, u32),
            y: u32,
        }
        let foo = Foo { x: (1, 2), y: 3 };

        match foo {
            Foo { x: (1, b), y } => println!("First of x is 1, b = {},  y = {} ", b, y),
            Foo { y: 2, x: i } => println!("y is 2, i = {:?}", i),
            Foo { y, .. } => println!("y = {}, we don't care about x", y),
        }
    }

    // match 与 if
    {
        let pair = (2, 2);
        match pair {
            (x, y) if x == y => println!("These are twins"),
            (x, y) if x + y == 0 => println!("Antimatter, kaboom!"),
            (x, _) if x % 2 == 1 => println!("The first one is odd"),
            _ => println!("No correlation..."),
        }
    }

    // @ 赋值
    {
        fn some_number() -> Option<u32> {
            Some(42)
        }

        match some_number() {
            Some(n @ 42) => println!("The Answer: {}!", n),
            Some(n)      => println!("Not interesting... {}", n),
                 _       => (),
        }
    }

    // if let
    {
        let number = Some(7);
        let letter: Option<i32> = None;
        let emoticon: Option<i32> = None;

        if let Some(i) = number {
            println!("Matched {:?}!", i);
        }

        if let Some(i) = letter {
            println!("Matched {:?}!", i);
        } else {
            println!("Didn't match a number. Let's go with a letter!");
        }

        let i_like_letters = false;

        if let Some(i) = emoticon {
            println!("Matched {:?}!", i);
        } else if i_like_letters {
            println!("Didn't match a number. Let's go with a letter!");
        } else {
            println!("I don't like letters. Let's go with an emoticon :)!");
        }
    }

    {
        enum Foo {Bar}

        let a = Foo::Bar;

        #[allow(irrefutable_let_patterns)]
        if let Foo::Bar = a {
            println!("a is foobar");
        } else {
            println!("aaa");
        }

    }

    // while let
    {
        let mut optional = Some(0);

        loop {
            match optional {
                Some(i) => {
                    if i > 9 {
                        println!("Greater than 9, quit!");
                        optional = None;
                    } else {
                        println!("`i` is `{:?}`. Try again.", i);
                        optional = Some(i + 1);
                    }
                },
                _ => { break; }
            }
        }

         while let Some(i) = optional {
            if i > 9 {
                println!("Greater than 9, quit!");
                optional = None;
            } else {
                println!("`i` is `{:?}`. Try again.", i);
                optional = Some(i + 1);
            }
        }
    }

}
